home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1995 June
/
MacFormat 25.iso
/
Shareware City
/
Developers
/
OutOfPhase1.1 Source
/
OutOfPhase Folder
/
WaveTableStorage.c
< prev
next >
Wrap
Text File
|
1994-08-15
|
11KB
|
324 lines
/* WaveTableStorage.c */
/*****************************************************************************/
/* */
/* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
/* Copyright (C) 1994 Thomas R. Lawrence */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
/* */
/*****************************************************************************/
#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"
#include "WaveTableStorage.h"
#include "Array.h"
#include "Memory.h"
#include "DataMunging.h"
struct WaveTableStorageRec
{
ArrayRec* ListOfTables; /* of char*s or short*s */
NumBitsType NumBits;
long NumFrames;
};
/* create a new wave table storage object */
WaveTableStorageRec* NewWaveTableStorage(NumBitsType NumBits, long NumFrames)
{
WaveTableStorageRec* Storage;
ERROR((NumBits != eSample8bit) && (NumBits != eSample16bit),
PRERR(ForceAbort,"NewWaveTableStorage: bad number of bits"));
ERROR((NumFrames != 2) && (NumFrames != 4) && (NumFrames != 8) && (NumFrames != 16)
&& (NumFrames != 32) && (NumFrames != 64) && (NumFrames != 128)
&& (NumFrames != 256) && (NumFrames != 512) && (NumFrames != 1024)
&& (NumFrames != 2048) && (NumFrames != 4096) && (NumFrames != 8192)
&& (NumFrames != 16384) && (NumFrames != 32768) && (NumFrames != 65536),
PRERR(ForceAbort,"NewWaveTableStorage: bad number of frames"));
Storage = (WaveTableStorageRec*)AllocPtrCanFail(sizeof(WaveTableStorageRec),
"WaveTableStorageRec");
if (Storage == NIL)
{
FailurePoint1:
return NIL;
}
Storage->ListOfTables = NewArray();
if (Storage->ListOfTables == NIL)
{
ReleasePtr((char*)Storage);
goto FailurePoint1;
}
Storage->NumBits = NumBits;
Storage->NumFrames = NumFrames;
return Storage;
}
/* dispose of the wave table storage object */
void DisposeWaveTableStorage(WaveTableStorageRec* Storage)
{
long Scan;
long Limit;
CheckPtrExistence(Storage);
Limit = ArrayGetLength(Storage->ListOfTables);
for (Scan = 0; Scan < Limit; Scan += 1)
{
ReleasePtr((char*)ArrayGetElement(Storage->ListOfTables,Scan));
}
DisposeArray(Storage->ListOfTables);
ReleasePtr((char*)Storage);
}
/* get the number of frames per table */
long WaveTableStorageNumFramesPerTable(WaveTableStorageRec* Storage)
{
CheckPtrExistence(Storage);
return Storage->NumFrames;
}
/* get the number of tables */
long WaveTableStorageNumTables(WaveTableStorageRec* Storage)
{
CheckPtrExistence(Storage);
return ArrayGetLength(Storage->ListOfTables);
}
/* get the number of bits for the wave table */
NumBitsType WaveTableStorageNumBits(WaveTableStorageRec* Storage)
{
CheckPtrExistence(Storage);
return Storage->NumBits;
}
/* get a reference to a table. this is NOT copied, and there is no type information. */
/* it is formatted as an array of characters for 8 bit data or array of shorts for */
/* 16 bit data. it contains (WaveTableStorageNumFramesPerTable + 1) elements for */
/* each table. The last element is a repeat of the first, and is provided for */
/* making anti-aliasing more efficient. */
void* WaveTableStorageGetTable(WaveTableStorageRec* Storage,
long Index)
{
CheckPtrExistence(Storage);
ERROR((Index < 0) || (Index >= ArrayGetLength(Storage->ListOfTables)),
PRERR(ForceAbort,"WaveTableStorageGetTable: index out of range"));
return ArrayGetElement(Storage->ListOfTables,Index);
}
/* append a new (zeroed out) table to the end of the array */
MyBoolean WaveTableStorageAppendEntry(WaveTableStorageRec* Storage)
{
char* Buffer;
long Limit;
long Scan;
CheckPtrExistence(Storage);
switch (Storage->NumBits)
{
default:
EXECUTE(PRERR(ForceAbort,
"WaveTableStorageAppendEntry: internal invalid num bits"));
break;
case eSample8bit:
Buffer = AllocPtrCanFail(Storage->NumFrames + 1,
"WaveTableStorageAppendEntry");
break;
case eSample16bit:
Buffer = AllocPtrCanFail(sizeof(short) * (Storage->NumFrames + 1),
"WaveTableStorageAppendEntry");
break;
}
if (Buffer == NIL)
{
FailurePoint1:
return False;
}
if (!ArrayAppendElement(Storage->ListOfTables,Buffer))
{
FailurePoint2:
ReleasePtr(Buffer);
goto FailurePoint1;
}
Limit = PtrSize(Buffer);
for (Scan = 0; Scan < Limit; Scan += 1)
{
Buffer[Scan] = 0;
}
return True;
}
/* put a value into a frame in a table */
void WaveTableStorageSetFrame(WaveTableStorageRec* Storage,
long TableIndex, long FrameIndex, largefixedsigned Value)
{
long NormalizedValue;
char* Reference;
CheckPtrExistence(Storage);
ERROR((TableIndex < 0) || (TableIndex >= ArrayGetLength(Storage->ListOfTables)),
PRERR(ForceAbort,"WaveTableStorageSetFrame: table index out of range"));
Reference = (char*)ArrayGetElement(Storage->ListOfTables,TableIndex);
ERROR((FrameIndex < 0) || (FrameIndex >= Storage->NumFrames),
PRERR(ForceAbort,"WaveTableStorageSetFrame: frame index out of range"));
switch (Storage->NumBits)
{
default:
EXECUTE(PRERR(ForceAbort,
"WaveTableStorageSetFrame: internal invalid num bits"));
break;
case eSample8bit:
NormalizedValue = roundtonearest(largefixed2double(Value) * MAX8BIT);
if (NormalizedValue < MIN8BIT)
{
NormalizedValue = MIN8BIT;
}
else if (NormalizedValue > MAX8BIT)
{
NormalizedValue = MAX8BIT;
}
PRNGCHK(Reference,&(((char*)Reference)[FrameIndex]),sizeof(char));
((char*)Reference)[FrameIndex] = NormalizedValue;
if (FrameIndex == 0)
{
PRNGCHK(Reference,&(((char*)Reference)[Storage->NumFrames]),
sizeof(char));
((char*)Reference)[Storage->NumFrames] = NormalizedValue;
}
break;
case eSample16bit:
NormalizedValue = roundtonearest(largefixed2double(Value) * MAX16BIT);
if (NormalizedValue < MIN16BIT)
{
NormalizedValue = MIN16BIT;
}
else if (NormalizedValue > MAX16BIT)
{
NormalizedValue = MAX16BIT;
}
PRNGCHK(Reference,&(((short*)Reference)[FrameIndex]),sizeof(short));
((short*)Reference)[FrameIndex] = NormalizedValue;
if (FrameIndex == 0)
{
PRNGCHK(Reference,&(((short*)Reference)[Storage->NumFrames]),
sizeof(short));
((short*)Reference)[Storage->NumFrames] = NormalizedValue;
}
break;
}
}
/* get a value from a frame in a table */
largefixedsigned WaveTableStorageGetFrame(WaveTableStorageRec* Storage,
long TableIndex, long FrameIndex)
{
double ReturnValue;
char* Reference;
CheckPtrExistence(Storage);
ERROR((TableIndex < 0) || (TableIndex >= ArrayGetLength(Storage->ListOfTables)),
PRERR(ForceAbort,"WaveTableStorageGetFrame: table index out of range"));
Reference = (char*)ArrayGetElement(Storage->ListOfTables,TableIndex);
ERROR((FrameIndex < 0) || (FrameIndex >= Storage->NumFrames),
PRERR(ForceAbort,"WaveTableStorageGetFrame: frame index out of range"));
switch (Storage->NumBits)
{
default:
EXECUTE(PRERR(ForceAbort,
"WaveTableStorageGetFrame: internal invalid num bits"));
break;
case eSample8bit:
PRNGCHK(Reference,&(((char*)Reference)[FrameIndex]),sizeof(char));
ReturnValue = ((double)((signed char*)Reference)[FrameIndex]) / MAX8BIT;
break;
case eSample16bit:
PRNGCHK(Reference,&(((short*)Reference)[FrameIndex]),sizeof(short));
ReturnValue = ((double)((signed short*)Reference)[FrameIndex]) / MAX16BIT;
break;
}
return double2largefixed(ReturnValue);
}
/* make a duplicate of the wave table */
WaveTableStorageRec* WaveTableDuplicate(WaveTableStorageRec* Original)
{
WaveTableStorageRec* Copy;
long Limit;
long Scan;
CheckPtrExistence(Original);
Copy = (WaveTableStorageRec*)AllocPtrCanFail(sizeof(WaveTableStorageRec),
"WaveTableStorageRec");
if (Copy == NIL)
{
FailurePoint1:
return NIL;
}
Copy->NumBits = Original->NumBits;
Copy->NumFrames = Original->NumFrames;
Copy->ListOfTables = NewArray();
if (Copy->ListOfTables == NIL)
{
FailurePoint2:
ReleasePtr((char*)Copy);
goto FailurePoint1;
}
Limit = ArrayGetLength(Original->ListOfTables);
for (Scan = 0; Scan < Limit; Scan += 1)
{
char* SliceCopy;
SliceCopy = CopyPtr((char*)ArrayGetElement(Original->ListOfTables,Scan));
if (SliceCopy == NIL)
{
/* bummer */
FailurePoint3:
Limit = ArrayGetLength(Copy->ListOfTables);
for (Scan = 0; Scan < Limit; Scan += 1)
{
ReleasePtr((char*)ArrayGetElement(Copy->ListOfTables,Scan));
}
DisposeArray(Copy->ListOfTables);
goto FailurePoint2;
}
SetTag(SliceCopy,"WaveTableStorageAppendEntry");
if (!ArrayAppendElement(Copy->ListOfTables,SliceCopy))
{
FailurePoint3a:
ReleasePtr((char*)SliceCopy);
goto FailurePoint3;
}
}
return Copy;
}